package com.binc.testspring.study.nio.netty.groupChat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;

/**
 * FileName: Netty_group_chat_server  netty编写群聊室  要求与当时nio写的群聊室一样
 * Autho: binC
 * Date:  2022/4/20 16:19
 */
@Slf4j
public class Netty_group_chat_server {

    private int port;

    public Netty_group_chat_server(int port) {
        this.port = port;
    }


    public static void main(String[] args) {
        Netty_group_chat_server server = new Netty_group_chat_server(9999);
        server.startup();
    }



    /**
     * 启动服务端,接受客户端的请求
     */
    public void startup(){
        //创建BossGroup 和 WorkerGroup
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workGroup = new NioEventLoopGroup(); // 没有参数试试创建8个子线程数
        try {

            //创建服务器端的启动对象,并配置参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            //使用链式编程对启动对象进行设置
            serverBootstrap.group(bossGroup, workGroup) // 服务端启动对象设置两个线程组       客户端的只需要设置一个
                    .channel(NioServerSocketChannel.class) // 使用NioServerSocketChannel作为服务器的通道实现
                    .option(ChannelOption.SO_BACKLOG, 128) // 设置线程队列等待连接个数
                    // .handler(null) // 该handler来对应bossGroup;   childHandler 对应workerGroup
                    .childOption(ChannelOption.SO_KEEPALIVE, true) // 设置包hi活动连接状态
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast("decoder",new StringDecoder());
                            pipeline.addLast("encoder",new StringEncoder());
                            pipeline.addLast(new Netty_group_chat_server_childChannel());
                        }
                    }); // 给我们的workerGroup组的 eventLoop 对应的管道设置处理器    即:真正的业务处理器;  这才我们开发中真正最关心的消息的处理逻辑  其他的都是服务器和客户端的设置
                        //原本这里是匿名对象进行设置的,现在这个配置的对象有点多了,我们但对建立一个类去设置

            log.info("===== 服务器端 设置完成了=====");

            //绑定一个端口并且同步生成了一个 ChannelFuture 对象（也就是立马返回这样一个对象）
            //启动服务器(并绑定端口)
            ChannelFuture channelFuture = serverBootstrap.bind(port);

            //给channelFuture 注册监听器，监控我们关心的事件
            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture cf) throws Exception {
                    if (cf.isSuccess()) {
                        log.info("=====监听端口{}成功=====", port);
                    } else {
                        log.info("=====监听端口{}失败=====", port);
                    }
                }
            });

            //对关闭通道时间进行监听
            channelFuture.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }



}
